package com.indeep.user.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.indeep.common.core.UserSubject;
import com.indeep.common.emun.RedisKeys;
import com.indeep.common.err.InDeepException;
import com.indeep.common.result.JsonResult;
import com.indeep.common.result.StatusCode;
import com.indeep.common.utils.DataUtils;
import com.indeep.common.utils.StringProcessingUtils;
import com.indeep.user.constant.LevelAndExp;
import com.indeep.user.dto.feign.UserPostsDetailDTO;
import com.indeep.user.dto.UpdatePrivacySettingDTO;
import com.indeep.user.dto.feign.UserPostsDetaiLDTO;
import com.indeep.user.feign.CommunityFeignClient;
import com.indeep.user.mapper.*;
import com.indeep.user.mapper.po.*;
import com.indeep.user.service.AppUserService;
import com.indeep.user.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service("appUserServiceImpl")
@Transactional
public class AppUserServiceImpl implements AppUserService {
    @Autowired
    AppUserMapper appUserMapper;
    
    @Autowired
    AppUserAuditMapper appUserAuditMapper;
    @Autowired
    AppUserPortraitMapper appUserPortraitMapper;
    @Resource
    CommunityFeignClient communityFeignClient;
    
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    AppExperienceLevelMapper appExperienceLevelMapper;
    
    @Autowired
    AppRemarkMapper appRemarkMapper;
    
    @Autowired
    private AppFollowMapper appFollowMapper;
    
    @Autowired
    private AppBlacklistMapper appBlacklistMapper;
    
    @Autowired
    private AppUserSettingMapper appUserSettingMapper;
    
    @Autowired
    private AppPostContentMapper appPostContentMapper;

    @Value("${posts.level.postId:1}")
    private Long postId;
    
    @Override
    public AppConfigVO login() {
        Long userId = UserSubject.getCurrentUserId();
        if (userId == null) {
            throw new InDeepException("用户未登录");
        }
        AppUserPO appUserPO = new AppUserPO();
        appUserPO.setId(userId);
        appUserPO.setLastLoginDatetime(new Date());
        appUserMapper.updateById(appUserPO);
        // 记录活跃用户数
        String key = RedisKeys.ACTIVE_NUM + DataUtils.getCurrentDate();
        redisTemplate.opsForValue().setBit(key, userId.intValue(), true);
        if (redisTemplate.opsForValue().get(RedisKeys.APP_CONFIG) != null) {
            return JSON.parseObject(redisTemplate.opsForValue().get(RedisKeys.APP_CONFIG).toString(), AppConfigVO.class);
        }
        return null;
    }
    
    @Override
    public DataExperienceVO getUserInfo() {
        // 从token中获取手机号
        Long userId = UserSubject.getCurrentUserId();
        if (userId == 0) {
            throw new InDeepException(StatusCode.LOGIN_ERROR);
        }
        
        // 查询用户信息和用户经验
        AppUserPO appUserDO = appUserMapper.selectById(userId);
        QueryWrapper<AppExperienceLevelPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", appUserDO.getId());
        AppExperienceLevelPO appExperienceLevelDO = appExperienceLevelMapper.selectOne(queryWrapper);
        if (appExperienceLevelDO == null) {
            appExperienceLevelDO = new AppExperienceLevelPO(null,
                    userId, 0L, null, null);
            appExperienceLevelMapper.insert(appExperienceLevelDO);
        }
        
        Integer exp = Math.toIntExact(appExperienceLevelDO.getExp());
        
        // 获取城市
        String city = null;
        // 解析性别
        String sex = Sexes.getByIndex(appUserDO.getSex()).str;
        // 帖子数和帖子被点赞总和
        JsonResult<UserPostsDetailDTO> result = communityFeignClient.queryCurrentUserPostsDetail(0L);
        if (result.getCode() != 200) {
            throw new InDeepException("服务器异常");
        }
        UserPostsDetailDTO content = result.getContent();
        int days = Math.toIntExact((System.currentTimeMillis() - appUserDO.getCreateTime().getTime())
                / 24 / 60 / 60 / 1000);
        // 构造UserBasicInfoBO类和UserExpInfo类
        String birthday = appUserDO.getBirthday() == null ? "" :
                new SimpleDateFormat("yyyy-MM-dd").format(appUserDO.getBirthday());
        String encodeUserId = StringProcessingUtils.getEncodeUserId(userId);
        UserBasicInfoVO basicInfoBO = new UserBasicInfoVO(appUserDO.getId(), encodeUserId, appUserDO.getUsername(),
                appUserDO.getAvatar(), appUserDO.getTel(), appUserDO.getArea() == null ? "" :
                appUserDO.getArea(), sex, appUserDO.getSignature(), "1", content.getCount(), content.getLikes(), appUserDO.getFans(),
                appUserDO.getFollow(), birthday, "" + days + "", appUserDO.getBackgroundPicture(),
                content.getComePost(), postId, content.getLike());
        UserExpInfoVO expInfo = new UserExpInfoVO(new LevelAndExp(exp), true);
        return new DataExperienceVO(basicInfoBO, expInfo);
    }
    
    @Override
    public DataExperienceVO queryHomepage(Long userId) {
        Long currentUserId = UserSubject.getCurrentUserId();
        Long userTel = UserSubject.getCurrentUserTel();
        // 从token中获取手机号
        if (userTel == 0 || currentUserId == 0) {
            throw new InDeepException(StatusCode.LOGIN_ERROR);
        }
        if (userId == 0) userId = currentUserId;
        // 查询备注表信息
        LambdaQueryWrapper<AppRemarkPO> query = new LambdaQueryWrapper<>();
        query.eq(AppRemarkPO::getUserId, currentUserId).eq(AppRemarkPO::getToUserId, userId);
        AppRemarkPO data = appRemarkMapper.selectOne(query);
        // 查询用户信息
        AppUserPO appUserDO = appUserMapper.selectById(userId);
        if (appUserDO == null) return null;
        
        // 帖子数和帖子被点赞总和
        JsonResult<UserPostsDetailDTO> result = communityFeignClient.queryCurrentUserPostsDetail(0L);
        if (result.getCode() != 200) {
            throw new InDeepException("服务器异常");
        }
        UserPostsDetailDTO content = result.getContent();
        
        // 查询是否是在黑名单和是否已关注
        QueryWrapper<AppFollowPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", currentUserId)
                .eq("follow_user_id", userId)
                .eq("status", 1);
        boolean isFollowed = appFollowMapper.exists(queryWrapper);
        
        QueryWrapper<AppBlacklistPO> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("operational_user", userId)
                .eq("shielded_user", currentUserId)
                .eq("status", 1);
        boolean isBlack = appBlacklistMapper.exists(queryWrapper1);
        JsonResult<List<IdNameImageUrlIsNewCPO>> followResult = communityFeignClient.queryUserFollowCommunity(userId);
        if (followResult.getCode() != 200) {
            throw new InDeepException("服务接口异常");
        }
        //是否显示粉丝数和关注数
        QueryWrapper<AppBlacklistPO> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.eq("operational_user", userId)
                .eq("shielded_user", currentUserId);
        AppBlacklistPO appBlacklistDO = appBlacklistMapper.selectOne(queryWrapper3);
        // 查别人主页情况下
        AppUserSettingPO appUserSettingDO = new AppUserSettingPO();
        if (!Objects.equals(userId, currentUserId)) {
            QueryWrapper<AppUserSettingPO> queryWrapper4 = new QueryWrapper<>();
            queryWrapper4.eq("user_id", userId);
            appUserSettingDO = appUserSettingMapper.selectOne(queryWrapper4);
        }
        
        if ((appBlacklistDO != null && appBlacklistDO.getShowFans() == 0) || isBlack || (appUserSettingDO.getFansDisplay() != null && appUserSettingDO.getFansDisplay() == 0)) {
            appUserDO.setFans(-1);
        }
        if ((appBlacklistDO != null && appBlacklistDO.getShowFollow() == 0) || isBlack || (appUserSettingDO.getFollowDisplay() != null && appUserSettingDO.getFollowDisplay() == 0)) {
            appUserDO.setFollow(-1);
        }
        
        // 查询用户信息和用户经验
        QueryWrapper<AppExperienceLevelPO> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("user_id", appUserDO.getId());
        AppExperienceLevelPO appExperienceLevelDO = appExperienceLevelMapper.selectOne(queryWrapper2);
        if (appExperienceLevelDO == null) {
            appExperienceLevelDO = new AppExperienceLevelPO(null,
                    currentUserId, 0L, null, null);
            appExperienceLevelMapper.insert(appExperienceLevelDO);
        }
        Integer exp = Math.toIntExact(appExperienceLevelDO.getExp());
        UserExpInfoVO expInfo = new UserExpInfoVO(new LevelAndExp(exp), true);
        
        // 转化为UserHomeInfoBO
        UserHomeInfoVO basicInfoBO = new UserHomeInfoVO(appUserDO.getId(), data == null || data.getRemark() == null || data.getRemark().isEmpty() ?
                appUserDO.getUsername() : appUserDO.getUsername() + '(' + data.getRemark() + ')',
                Sexes.getByIndex(appUserDO.getSex()).str, appUserDO.getSignature(), appUserDO.getAvatar(),
                appUserDO.getBackgroundPicture(), appUserDO.getFollow(), appUserDO.getFans(), content.getCount(), isBlack ||
                (appUserSettingDO.getBeLikeDisplay() != null && appUserSettingDO.getBeLikeDisplay() == 0) ?
                -1 : content.getLikes(),
                followResult.getContent(), isFollowed + "", isBlack + "",
                (appBlacklistDO != null && appBlacklistDO.getShowLike() == 0) || isBlack ||
                        (appUserSettingDO.getLikeDisplay() != null && appUserSettingDO.getLikeDisplay() == 0) ? -1 : content.getLike());
        
        return new DataExperienceVO(basicInfoBO, expInfo);
    }

    @Override
    public void updateBasicInfo(UpdateBasicUserInfoDTO basicUserInfoDto) {
        Long userId = UserSubject.getCurrentUserId();
        Long userTel = UserSubject.getCurrentUserTel();
        // 从token中获取手机号
        if (userTel == 0 || userId == 0) {
            throw new InDeepException(StatusCode.LOGIN_ERROR);
        }
        Integer age = null;
        Integer sex = null;

        if(basicUserInfoDto.getSex()!=null){
            Sexes sex1 = Sexes.getByStr(basicUserInfoDto.getSex());
            if (sex1 != null) sex = sex1.index;
        }

        // 查当前用户信息DO
        AppUserPO appUserDO = appUserMapper.selectById(userId);

        // 用户昵称去特殊字符
        if (basicUserInfoDto.getUserName() != null) {
            String regEx = "[\n`~!@#$%^&*()+=|{}':;,\\[\\].<>/?！￥…（）—【】‘；：”“’。， 、？]";
            Pattern p = Pattern.compile(regEx);
            Matcher m = p.matcher(basicUserInfoDto.getUserName());

            // 将所有的特殊字符替换为空字符串
            basicUserInfoDto.setUserName(m.replaceAll("").trim());
        }

        // 过滤不合法信息
        if (Objects.equals(basicUserInfoDto.getPhoto(), ""))
            basicUserInfoDto.setPhoto(null);
        if (Objects.equals(basicUserInfoDto.getBackgroundPhoto(), ""))
            basicUserInfoDto.setBackgroundPhoto(null);
        if (Objects.equals(basicUserInfoDto.getUserName(), ""))
            basicUserInfoDto.setUserName("名字不能为空");
        if (Objects.equals(basicUserInfoDto.getCity(), ""))
            basicUserInfoDto.setCity("地区不能为空");

        // 如果更新了生日则写入redis
        if (basicUserInfoDto.getBirthday() != null) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            try {
                Date parse = simpleDateFormat.parse(basicUserInfoDto.getBirthday());
                String key2 = "data_analysis:user_birthday:" + userId;
                redisTemplate.opsForValue().set(key2, simpleDateFormat.format(parse));
            } catch (ParseException e) {
                new InDeepException(StatusCode.BIRTHDAY_FORMAT_WRONG);
            }
        }

        // 用户更新头像和背景后，新增或更新一条审核条件
        AppUserAuditPO appUserAuditDO = new AppUserAuditPO(userId, 1);
        appUserAuditMapper.insertOrUpdate(appUserAuditDO);

        // 更新userDO
        appUserDO.addBasicInfo(basicUserInfoDto);
        appUserMapper.updateById(appUserDO);

        age = appUserMapper.selectAgeByBirthday(appUserDO.getId());

        QueryWrapper<AppUserPortraitPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",appUserDO.getId());
        AppUserPortraitPO appUserPortraitDO = new AppUserPortraitPO();
        appUserPortraitDO.setAge(age);
        appUserPortraitDO.setSex(sex);
        appUserPortraitMapper.update(appUserPortraitDO,queryWrapper);

        // 把更新后的的用户缓存到redis中
        redisTemplate.opsForValue().set(RedisKeys.USER + appUserDO.getId(), JSON.toJSONString(appUserDO));

        // 提示IM更新头像
        redisTemplate.convertAndSend("user.update", appUserDO.getId().toString());


    }

    @Override
    public void updatePrivacySetting(UpdatePrivacySettingDTO dto) {
        Long userId = UserSubject.getCurrentUserId();
        Long userTel = UserSubject.getCurrentUserTel();
        // 从token中获取手机号
        if (userTel == 0 || userId == 0) {
            throw new InDeepException(StatusCode.LOGIN_ERROR);
        }

        AppUserSettingPO appUserSettingDO = new AppUserSettingPO(dto, userId);
        UpdateWrapper<AppUserSettingPO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("user_id", userId);

        if (dto.getPostTime() != null) {
            appPostContentMapper.updateInvisibleTime(userId, dto.getPostTime());
        }

         appUserSettingMapper.update(appUserSettingDO, updateWrapper);

    }

    @Override
    public Privacy1VO getPrivacy() {
        Long userId = UserSubject.getCurrentUserId();
        Long userTel = UserSubject.getCurrentUserTel();
        // 从token中获取手机号
        if (userTel == 0 || userId == 0) {
            throw new InDeepException(StatusCode.LOGIN_ERROR);
        }
        QueryWrapper<AppUserSettingPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        AppUserSettingPO appUserSettingDO = appUserSettingMapper.selectOne(queryWrapper);
        return new Privacy1VO(appUserSettingDO);
    }
}
